package com.huanletao.quartz.utils;

import com.huanletao.quartz.entity.JobDetails;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.MethodUtils;

import java.lang.reflect.InvocationTargetException;

/**
 * description: ReflectUtils <br>
 * date: 2022/7/3 11:39 <br>
 * author: 踏雪无痕 <br>
 * version: 1.0 <br>
 */
public class ReflectUtils {

    /**
     * 反射执行方法；
     *
     * @param jobDetails
     */
    public static void invokeMethod(JobDetails jobDetails) throws Exception {
        String targetName = jobDetails.getTargetName();
        //获取实例；
        String beanName = getBeanName(targetName);
        String methodName = getMethodName(targetName);
        Object[] methodParams = getParams(targetName);
        if (!isValidClassName(beanName)) {
            Object bean = SpringUtils.getBean(beanName);
            invokeMethod(bean, methodName, methodParams);
        } else {
            Object bean = Class.forName(beanName).newInstance();
            invokeMethod(bean, methodName, methodParams);
        }
    }

    private static boolean isValidClassName(String invokeTarget) {
        return StringUtils.countMatches(invokeTarget, ".") > 1;
    }

    private static void invokeMethod(Object bean, String methodName, Object[] methodParams) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
        MethodUtils.invokeMethod(bean, methodName, methodParams);
    }

    private static String getMethodName(String targetName) {
        String methodName = StringUtils.substringBefore(targetName, "(");
        return StringUtils.substringAfterLast(methodName, ".");
    }

    private static String getBeanName(String targetName) {
        String beanName = StringUtils.substringBefore(targetName, "(");
        return StringUtils.substringBeforeLast(beanName, ".");
    }

    private static Object[] getParams(String targetName) {
        String paramStr = StringUtils.substringBetween(targetName, "(", ")");
        String[] paramStrArrs = StringUtils.split(paramStr, ",");
        Object[] params = new Object[paramStrArrs.length];
        for (int i = 0; i < paramStrArrs.length; i++) {
            String temp = paramStrArrs[i];
            if (StringUtils.startsWithAny(temp, "'", "\"")) {
                params[i] = StringUtils.substring(temp, 1, temp.length() - 1);
            } else if (StringUtils.endsWith(temp, "L")) {
                params[i] = Long.parseLong(StringUtils.substring(temp, 0, temp.length() - 1));
            } else if (StringUtils.endsWith(temp, "D")) {
                params[i] = Double.parseDouble(StringUtils.substring(temp, 0, temp.length() - 1));
            } else {
                params[i] = Integer.parseInt(temp);
            }
        }
        return params;
    }
}
